#ifndef DSPSIMULATOR_CONTEXT_DSPCONTEXT_H
#define DSPSIMULATOR_CONTEXT_DSPCONTEXT_H

#include "simulator/type/type.h"
#include "simulator/instruction/executePhase.h"
#include <vector>

namespace dspsimulator {
    /**
     * @brief 用于表示一条延时槽指令的上下文元素
     */
    struct Element {
        /**
         * @brief 延时槽指令的地址
         */
        u32 m_address{0};
        /**
         * @brief 延时槽指令的当前执行阶段
         */
        simulator::ExecutePhase m_phase{simulator::ExecutePhase::E1};
    };

    /**
     * @brief 一个翻译IR块对应的上下文信息。相同上下文情况下可使用同一翻译IR块
     */
    class DSPContext {
    public:
        /**
         * @brief 上下文的==比较函数
         * @param other 比较的上下文对象
         * @return 如果两个上下文相同，返回true，否则返回false
         */
        bool operator==(const DSPContext &other) const {
            if (m_entry_address != other.m_entry_address) {
                return false;
            }

            if (m_elements.size() != other.m_elements.size()) {
                return false;
            }
            std::size_t size = m_elements.size();
            auto iter = m_elements.begin();
            auto other_iter = other.m_elements.begin();
            for (u32 i = 0; i < size; ++i) {
                if (iter->m_address != other_iter->m_address) {
                    return false;
                }
                if (iter->m_phase != other_iter->m_phase) {
                    return false;
                }
                ++iter;
                ++other_iter;
            }
            return true;
        }

        /**
         * @brief 翻译的入口地址
         */
        u32 m_entry_address{0};
        /**
         * @brief 延时槽指令提取的上下文元素
         */
        std::vector<Element> m_elements;
    };

    /**
     * @brief 翻译块的hash函数
     */
    struct DSPContextHash {
        std::size_t operator()(const DSPContext &dsp_context) const {
            std::size_t hash = std::hash<u32>()(dsp_context.m_entry_address);
            for (const auto &m_element: dsp_context.m_elements) {
                hash ^= std::hash<u32>()(m_element.m_address);
                hash ^= std::hash<u32>()(static_cast<u32>(m_element.m_phase));
            }
            return hash;
        }
    };
}

#endif //DSPSIMULATOR_CONTEXT_DSPCONTEXT_H
